#include "dialog.h"
#include "ui_dialog.h"
//json对象
QJsonObject json;//构造一个空的 JSON 对象,用于进行点表下发

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),hasShownWarning(false),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    setWindowTitle("基于边缘网关的空调实验室测试监护系统");
    //创建udp对象
    udpSocket = new QUdpSocket(this);
    //创建tcp客户端对象
    socket = new QTcpSocket(this);
    //创建tcp文件对象
    fliesocket=new QTcpSocket(this);
    //发送广播槽函数
    connect(ui->pushButtonSearch,SIGNAL(clicked()),this,SLOT(btnSearchSlot()));
    //接收广播回复
    connect(udpSocket, SIGNAL(readyRead()), this,SLOT(udpRecvSlot()));
    //建立第一个TCP连接
    connect(ui->pushButtonLogin,SIGNAL(clicked()),this,SLOT(btnLoginSlot()));
    //接收服务器数据
    connect(socket,SIGNAL(readyRead()),this,SLOT(n1tcpReadSlot()));
    //第二个tcp发送文件
    connect(fliesocket,SIGNAL(connected()),this,SLOT(connectFileSlot()));
    //点击心跳包按钮
    connect(ui->pushButtonHeart,SIGNAL(clicked()),this,SLOT(btnHeartSlot()));
}

Dialog::~Dialog()
{
    delete ui;
    udpSocket->close();
    socket->close();
}
//进行UDP广播
void Dialog::btnSearchSlot()
{
    //绑定广播地址
    QHostAddress broadcastAddress(UDPIP);//要将广播消息发送到的目标网络地址

    QByteArray datagram = "group2"; // 你想要广播的消息

    if (udpSocket->writeDatagram(datagram, datagram.size(), broadcastAddress, 8888))
    { // 8888是端口号,接收广播消息的程序需要在这个端口号上监听才能正确接收到广播消息。
        // 消息成功发送
        qDebug()<<"广播成功";//将数据报大小的数据发送到端口的主机地址。返回成功时发送的字节数,字节数>0成功
    } else {
        // 消息发送失败
        qDebug()<<"广播失败";
    }
}
//接收tcp服务器数据
void Dialog::n1tcpReadSlot()
{
    if (socket->state() == QAbstractSocket::ConnectedState) {
        // 继续进行发送数据等操作，比如调用waitForBytesWritten() 等
    } else {
        qDebug() << "套接字未连接，无法发送数据";
    }
    QByteArray buffer = socket->readAll();
    // QByteArray → QString
    QString text(buffer);
    if(text=="yes")
    {
        QMessageBox::information(this,"信息","tcp连接成功");
        json["type"] = 1;//将json格式 "type" 字段的值设置为 1。
        // 创建JSON文档
        QJsonDocument jsonDoc(json);
        // 将JSON文档转换为字节数组
        QByteArray jsonData = jsonDoc.toJson();
        // 发送JSON数据
        socket->write(jsonData);

        //建立第二个TCP连接
        fliesocket->connectToHost(tcpip,8001);
    }
    else if(text == "living")//进程存活
    {
        qDebug()<<"process living";
    }
    else
        qDebug()<<"tcp连接失败";
}
//建立TCP连接
void Dialog::btnLoginSlot()
{
    //建立第一个TCP连接
    socket->connectToHost(tcpip,8888);
    ui->pushButtonLogin->setText("已连接");
}
 //接收广播回复
void Dialog::udpRecvSlot()
{
    while (udpSocket->hasPendingDatagrams()) //如果至少有一个数据报等待读取，则返回 true；否则返回 false。
    {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());//resize 调整缓冲区大小以适应接收到的数据量
        //pendingDatagramSize返回第一个挂起的 UDP 数据报的大小。如果没有可用的数据报，此函数返回 - 1。
        QHostAddress sender;//发送者的ip地址
        quint16 senderPort;//发送者端口号
        udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);//读取接收到的数据放到data中
        tcpip = sender.toString();//获取服务器ip地址
        // 打印发送者地址和接收到的数据
        qDebug() << "Received datagram from:" << sender.toString() << datagram.data();
         ui->textBrowser->append("搜索到设备ip:");
        ui->textBrowser->append(sender.toString());
        udpSocket->close();//关闭广播
    }
}
//发送文件
void Dialog::connectFileSlot()
{
    QFile readFile(":/new/prefix1/node.json");
    readFile.open(QIODevice::ReadOnly);//以只读方式读取文件
    QByteArray file;  //用于存储即将读取的文件内容。
    qint64 totalSize = readFile.size();//获取到文件的总大小
    qDebug()<<totalSize;
    file = readFile.read(totalSize);//读取文件的全部内容
    qDebug()<<file;
    fliesocket->write(file);//向设备发送文件
}
//心跳包
void Dialog::heartTimerSlot()
{
        // 添加其他键值对
        json["type"] = 3;
        // 创建JSON文档
        QJsonDocument jsonDoc(json);

        // 将JSON文档转换为字节数组
        QByteArray jsonData = jsonDoc.toJson();

        // 发送JSON数据
        socket->write(jsonData);

        // 等待数据发送完毕
        if (socket->waitForBytesWritten()) {
             qDebug() << "JSON data sent successfully";
        }
        else {
            qDebug() << "Failed to send JSON data";
            if (!hasShownWarning) {
                        QMessageBox::warning(this, "警告", "已退出心跳包");
                        hasShownWarning = true; // 设置为true，表示警告已经显示过
                    }
        }
}

void Dialog::btnHeartSlot()
{
    // 创建定时器，每隔1秒发送心跳包
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this,SLOT(heartTimerSlot()));
    timer->start(1000); // 1000毫秒为间隔
}
